#include <gtk/gtk.h>
#include <jni.h>
#include "gtkwire_gobject_GtkTreeModel.h"
#include "gtkwire_utils.h"
#include "gtkwire_treemodel.h"
#include "gtkwire_databank.h"

static void 			set_fail_flag		();

static JavaVM *jvm = NULL;

static GtkCellRenderer *current_cell;
static jclass treemodel_cls = 0;
static jmethodID cell_rend_mid  = 0;

void
init_tree_model( JNIEnv *env)
{
	/* Initialize the jvm global variable */
	(*env)->GetJavaVM (env, &jvm);

	jclass loc_cls = (*env)->FindClass (env, "gtkwire/gobject/GtkTreeModel");
	treemodel_cls = (*env)->NewGlobalRef (env, loc_cls);
	cell_rend_mid = (*env)->GetStaticMethodID(env, treemodel_cls, "cellRenderCallBack", "(ILjava/lang/String;)V");
}

//------------------------------------------------------------------ FAIL FLAG
static void
set_fail_flag()
{

}
//------------------------------------------------------------------ GET
/* model get */
JNIEXPORT jobject JNICALL Java_gtkwire_gobject_GtkTreeModel_getValue
  (JNIEnv *env, jobject obj, jint model_id, jint column, jstring path)
{
	GtkTreeModel *tree_model = GTK_TREE_MODEL (get_g_object(model_id));
	const char *path_str = (*env)->GetStringUTFChars (env, path, NULL);

	GtkTreeIter iter;
	gboolean success = gtk_tree_model_get_iter_from_string (tree_model,
								&iter,
         	                                             	path_str);
	if (!success )
	{
		set_fail_flag ();
		(*env)->ReleaseStringUTFChars(env, path, path_str);
		return;
	}

	GValue value = { 0, };
	gtk_tree_model_get_value (	tree_model,
					&iter,
					column,
					&value);

	(*env)->ReleaseStringUTFChars(env, path, path_str);

	return get_jobject_for_GValue(env, &value );
}


//--------------------------------------------------------------------- SET
/* model list store set int */
JNIEXPORT void JNICALL Java_gtkwire_gobject_GtkTreeModel_setIntLS
  (JNIEnv *env, jobject obj, jint list_id, jstring path, jint column, jint value)
{
	GtkListStore *list_store = GTK_LIST_STORE (get_g_object(list_id));
	const char *path_str = (*env)->GetStringUTFChars (env, path, NULL);

	GtkTreeIter iter;
	gboolean success = gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL(list_store),
								&iter,
								path_str);
	if (!success )
	{
		set_fail_flag ();
		(*env)->ReleaseStringUTFChars(env, path, path_str);
		return;
	}

	GValue gval = { 0, };
	g_value_init (&gval, G_TYPE_INT);
	g_value_set_int (&gval, value);

	gtk_list_store_set_value (list_store, &iter, column, &gval);

	(*env)->ReleaseStringUTFChars(env, path, path_str);
}

JNIEXPORT void JNICALL Java_gtkwire_gobject_GtkTreeModel_setStringLS
  (JNIEnv *env, jobject obj, jint list_id, jstring path, jint column, jstring value)
{
	GtkListStore *list_store = GTK_LIST_STORE (get_g_object(list_id));
	const char *path_str = (*env)->GetStringUTFChars (env, path, NULL);
	const char *val_str = (*env)->GetStringUTFChars (env, value, NULL);

	GtkTreeIter iter;
	gboolean success = gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL(list_store),
								&iter,
								path_str);
	if (!success )
	{
		set_fail_flag ();
		(*env)->ReleaseStringUTFChars(env, path, path_str);
		return;
	}

	GValue gval = { 0, };
	g_value_init (&gval, G_TYPE_STRING);
	g_value_set_string (&gval, val_str);

	gtk_list_store_set_value (list_store, &iter, column, &gval);

	(*env)->ReleaseStringUTFChars(env, path, path_str);
	(*env)->ReleaseStringUTFChars(env, value, val_str);
}

JNIEXPORT void JNICALL Java_gtkwire_gobject_GtkTreeModel_setBooleanLS
  (JNIEnv *env, jobject obj, jint list_id, jstring path, jint column, jboolean value)
{
	GtkListStore *list_store = GTK_LIST_STORE (get_g_object(list_id));
	const char *path_str = (*env)->GetStringUTFChars (env, path, NULL);

	GtkTreeIter iter;
	gboolean success = gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL(list_store),
								&iter,
								path_str);
	if (!success )
	{
		set_fail_flag ();
		(*env)->ReleaseStringUTFChars(env, path, path_str);
		return;
	}
	GValue gval = { 0, };
	g_value_init (&gval, G_TYPE_BOOLEAN);
	g_value_set_boolean (&gval, value);

	gtk_list_store_set_value (list_store, &iter, column, &gval);

	(*env)->ReleaseStringUTFChars(env, path, path_str);
}

JNIEXPORT void JNICALL Java_gtkwire_gobject_GtkTreeModel_setGObjectLS
  (JNIEnv *env, jobject obj, jint list_id, jstring path, jint column,  jint g_id)
{
	GtkListStore *list_store = GTK_LIST_STORE (get_g_object(list_id));
	const char *path_str = (*env)->GetStringUTFChars (env, path, NULL);

	GObject *gobj;
	gobj = get_g_object (g_id);

	GtkTreeIter iter;
	gboolean success = gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL(list_store),
								&iter,
								path_str);
	if (!success )
	{
		set_fail_flag ();
		(*env)->ReleaseStringUTFChars(env, path, path_str);
		return;
	}
	GValue gval = { 0, };
	g_value_init (&gval, G_OBJECT_TYPE(gobj));
	g_value_set_object (&gval, gobj);

	gtk_list_store_set_value (list_store, &iter, column, &gval);

	(*env)->ReleaseStringUTFChars(env, path, path_str);
}


//------------------------------------------------------- DATA FUNC CELL RENDERING


JNIEXPORT void JNICALL Java_gtkwire_gobject_GtkTreeModel_registerDataFuncN
  (JNIEnv *env, jobject obj, jint tree_column_id, jint cell_rend_id, jint datafunc_id )
{
	gpointer key;
	key = int_key (datafunc_id);
	
	GtkTreeViewColumn *tree_column = GTK_TREE_VIEW_COLUMN(get_g_object (tree_column_id));
	GtkCellRenderer *renderer = GTK_CELL_RENDERER( get_g_object (cell_rend_id));

	gtk_tree_view_column_set_cell_data_func (	tree_column,
							renderer,
							java_cell_render_callback,
							key,
							NULL);
}

void  
java_cell_render_callback (	GtkTreeViewColumn *tree_column,
				GtkCellRenderer *cell,
				GtkTreeModel *tree_model,
				GtkTreeIter *iter,
				gpointer data)
{
	JNIEnv *env;
	if ((*jvm)->AttachCurrentThread (jvm, (void **)&env, NULL) != 0)
	{
		/* some error handling? */
		printf("jvm attach error");
	}

	current_cell = cell;
	int *cell_rend_id = data;
	const char *path = gtk_tree_model_get_string_from_iter (tree_model, iter);

	(*env)->CallStaticVoidMethod(env, treemodel_cls, cell_rend_mid, *cell_rend_id, (*env)->NewStringUTF (env, path ));

	cell = NULL;
}

JNIEXPORT void JNICALL Java_gtkwire_gobject_GtkTreeModel_set_1cell_1property
  (JNIEnv *env, jobject obj, jstring property, jint property_type, jstring value)
{
	GType type = get_gtype (property_type);

	const char *p_str = (*env)->GetStringUTFChars (env, property, NULL);
	const char *v_str = (*env)->GetStringUTFChars (env, value, NULL);

	GValue gval = get_gvalue (type, v_str);
	g_object_set_property (G_OBJECT(current_cell), p_str, &gval);

	(*env)->ReleaseStringUTFChars(env, property, p_str);
	(*env)->ReleaseStringUTFChars(env, value, v_str);
}

